Skip to content

C# Tools

Tools are the primary way to extend HPD-Agent with custom capabilities. A tool container is a class that contains one or more capabilities that the agent can use to accomplish tasks.

The Three Capability Types

HPD-Agent supports three types of capabilities, each suited for different use cases:

TypePurposeContainer?Use When
AIFunctionSingle, focused operationNoOne action, clear inputs/outputs
SkillMulti-function workflowYesGrouped functions with shared instructions
SubAgentDelegated agentNoComplex tasks requiring autonomous reasoning

AIFunction

A single function the agent can call. Best for discrete operations with clear inputs and outputs.

csharp
public class WeatherTools
{
    [AIFunction]
    [AIDescription("Get the current weather for a location")]
    public async Task<string> GetWeather(
        [AIDescription("City name (e.g., 'London', 'New York')")] string city)
    {
        // Implementation
    }
}

→ See 02.1.1 AIFunctions.md for details.

Skill

A group of related functions with shared instructions. When activated, the skill expands to reveal its constituent functions.

csharp
public class SearchTools
{
    [Skill]
    public Skill ResearchSkill()
    {
        return SkillFactory.Create(
            name: "Research",
            description: "Deep research across multiple sources",
            // Auto-generated: "Research skill activated. Available functions: WebSearch, CodeSearch"
            functionResult: null,  // Auto-generated message is sufficient
            systemPrompt: "1. Search web first\n2. Search code if relevant\n3. Synthesize findings",
            "SearchTool.WebSearch", "SearchTool.CodeSearch"
        );
    }
}

→ See 02.1.2 Skills.md for details.

SubAgent

A child agent that can be delegated tasks. SubAgents have their own configuration, Toolkits, and conversation thread.

csharp
public class DelegationTools
{
    [SubAgent]
    public SubAgent CodeReviewer()
    {
        return SubAgentFactory.Create(
            name: "Code Reviewer",
            description: "Reviews code for quality and best practices",
            agentConfig: new AgentConfig { SystemInstructions = "You are a code reviewer..." },
            typeof(FileSystemTools)
        );
    }
}

→ See 02.1.3 SubAgents.md for details.


Basic Registration

Register tools with the AgentBuilder:

csharp
var agent = new AgentBuilder()
    .WithTools<WeatherTools>()
    .WithTools<SearchTools>()
    .Build();

With Dependency Injection

If your tool requires services, use WithServiceProvider():

csharp
var services = new ServiceCollection()
    .AddSingleton<IWeatherService, WeatherService>()
    .BuildServiceProvider();

var agent = new AgentBuilder()
    .WithServiceProvider(services)
    .WithTools<WeatherTools>()
    .Build();

With Tool Metadata

Pass runtime context to control dynamic behavior:

csharp
var agent = new AgentBuilder()
    .WithTools<SearchTools>(new SearchMetadata
    {
        ProviderName = "Tavily",
        HasAdvancedFeatures = true
    })
    .Build();

→ See 02.1.4 Tool Metadata.md for details.


Decision Flowchart

Use this to choose the right capability type:

Is it a single, focused action?
├── Yes → AIFunction
└── No
    ├── Does it need multiple related functions with shared context?
    │   └── Yes → Skill
    └── Does it need autonomous multi-step reasoning?
        └── Yes → SubAgent

Examples:

TaskCapabilityWhy
Get weather for a cityAIFunctionSingle operation, clear I/O
Search and analyze resultsSkillMultiple functions, shared workflow
Review a pull requestSubAgentRequires reading, reasoning, commenting
Send an emailAIFunctionSingle operation
Research a topic thoroughlySkillWeb search + doc search + synthesis
Debug a complex issueSubAgentAutonomous investigation needed

Tool Collapsing

When you have many tools, the agent's context window can become cluttered. HPD-Agent supports collapsing Toolkits into containers that expand on demand.

Before expansion:          After expansion:
┌──────────────────┐       ┌──────────────────┐
│ SearchTools     │  ──►  │ WebSearch        │
│ (3 functions)    │       │ CodeSearch       │
└──────────────────┘       │ DocSearch        │
                           └──────────────────┘

→ See 02.1.5 Context Engineering.md for details.


Writing Instructions

Skills, SubAgents, and collapsed tools all use dual-context instructions to guide the agent:

ParameterLocationLifetimeUse For
functionResultConversation historyOne-timeAdditional context (appended to auto-generated message)
systemPromptSystem promptEvery turnCritical rules, workflow

Important: The system automatically generates a base activation/expansion message:

"{Name} skill activated. Available functions: {FunctionList}"
"{ToolkitName} expanded. Available functions: {FunctionList}"

Your functionResult is appended to this auto-generated message. Don't duplicate the activation info—use it only for additional context. Pass null if the auto-generated message is sufficient.

csharp
// Skill instructions - dual-context
SkillFactory.Create(
    name: "Research",
    description: "Deep research",
    // Auto-generated: "Research skill activated. Available functions: WebSearch, CodeSearch"
    functionResult: null,  // Auto-generated message is sufficient
    systemPrompt: @"
        1. Search web first
        2. Search code if relevant
        3. Synthesize findings",                    // Persistent
    ...
);

// Toolkit instructions - same dual-context
[Toolkit(
    "Database operations",
    // Auto-generated: "DatabaseTools expanded. Available functions: Query, Insert, Update, Delete"
    FunctionResult: "Connected to: production_db",  // Additional context only
    SystemPrompt: "CRITICAL: Never DELETE without WHERE clause"
)]

→ See 02.1.6 Writing Instructions.md for best practices.


Conditional Visibility

Show or hide capabilities based on runtime metadata using simple expressions:

csharp
// Simple boolean
[ConditionalFunction("HasAdvancedFeatures")]

// Comparison
[ConditionalFunction("ProviderCount > 1")]

// Boolean logic
[ConditionalFunction("HasTavily || HasBrave")]

// On parameters too
public Task<string> Search(
    string query,
    [ConditionalParameter("ProviderCount > 1")] string? provider = null)

→ See 02.1.7 Conditional Expression DSL.md for the full syntax.


Next Steps

Released under the MIT License.